
/*workfloe 编辑
  begin 2024/1/12
*/
(function ($) {
    $.fn.yqFlowEdit = function (opts, param) {
        if (typeof opts == 'string') {
            return $.fn.yqFlowEdit.methods[opts](this, param);
        }

        var $this = this;
        var opt;
        if ($this.data("yqtype") == "yqFlowEdit") {
            destroy($this);
        }

        opt = $.extend({}, $.fn.yqFlowEdit.defaults, opts);
        var $uniqueID = $this.attr("ID");
        if ($uniqueID === undefined || $uniqueID === null || $uniqueID == "") {
            $uniqueID = $.getUniqueID();
            $this.attr("ID", $uniqueID);
        }

        if (opt.width === undefined) {
            if ($this.width() > 0) {
                opt.width = $this.width();
            } else {
                opt.width = 450;
            }
        }
        else {
            $this.width(opt.width);
        }

        if (opt.height === undefined) {
            if ($this.height() > 0) {
                opt.height = $this.height();
            } else {
                opt.height = 400;
            }
        }
        else {
            $this.height(opt.height);
        }

        opt._flowstate = {};

        //变量信息
        $this.data("flowedit_opt", opt);
        $this.data("yqtype", "yqFlowEdit");

        LoadJsCss(function () {
            opt.beforeBindingTitle.call($this, function () {
                init_html($this);
            });
        });
    };

    $.fn.yqFlowEdit.defaults = {
        ajaxUrl: "/_db.html",
        menus: [],
        value: {},
        /*
        menus: [{
            id: "save",
            text: "保存",
            iconCls: "icon-save",
            onClick: function () {
                //saveDiagram($object);
                console.log("save", $(this));
            }
        }, {
            id: "open",
            text: "打开",
            iconCls: "icon-open",
            onClick: function () {

            }
        }],

        value: {
            "info": {
                "ver": "",
                "current": "",
                "name": "",
                "describe": "",
                "func": "",
                "db_name": "",
                "tb_name": "",
                "state_field": "",
                "state_func": "",
                "state_start": "",
                "state_start_name": "",
                "case_when": "",
                "parameter": "",
                "remark": null,
                "params": null
            },
            "node": [
                {
                    "category": "Start",
                    "key": 1,
                    "loc": "-172.50 -45",
                    "text": "Start",
                    "desc": "Start",
                    "size": "100 60"
                },
                {
                    "category": "Return",
                    "text": "Return",
                    "key": 2,
                    "loc": "345.50 55",
                    "desc": "Return",
                    "size": "100 60"
                },
                {
                    "category": "Judge",
                    "text": "Is data\ntree-like?",
                    "key": 3,
                    "loc": "85 259",
                    "desc": "Is data\ntree-like?",
                    "size": "140 60"
                },
                {
                    "category": "Exec",
                    "text": "Use a TreeModel",
                    "key": 4,
                    "loc": "-167.50 199",
                    "desc": "Use a TreeModel",
                    "size": "135 60"
                },
                {
                    "category": "Exec",
                    "text": "Use a GraphLinksModel",
                    "key": 5,
                    "loc": "364 296",
                    "desc": "Use a GraphLinksModel",
                    "size": "120 80"
                },
                {
                    "category": "Exec",
                    "text": "Create DIV for Diagram",
                    "key": 6,
                    "loc": "3 99",
                    "desc": "Create DIV for Diagram",
                    "size": "140 80"
                },
                {
                    "category": "Exec",
                    "text": "Create new Diagram associated with DIV",
                    "key": 7,
                    "loc": "193 122",
                    "desc": "Create new Diagram associated with DIV",
                    "size": "120 80"
                },
                {
                    "category": "Proc",
                    "text": "Style node templates",
                    "key": 8,
                    "loc": "-107.50 670",
                    "type": 2,
                    "desc": "Style node templates",
                    "size": "155 60"
                },
                {
                    "category": "Proc",
                    "text": "Add data to node/linkDataArray",
                    "key": 9,
                    "loc": "138 348",
                    "type": 2,
                    "desc": "Add data to node/linkDataArray",
                    "size": "120 80"
                },
                {
                    "category": "Exec",
                    "text": "Add data to nodeDataArray, including parent",
                    "key": 10,
                    "loc": "-176.50 374",
                    "desc": "Add data to nodeDataArray, including parent",
                    "size": "155 100"
                },
                {
                    "category": "Exec",
                    "text": "Style link templates",
                    "key": 11,
                    "loc": "128.50 672",
                    "desc": "Style link templates",
                    "size": "135 60"
                },
                {
                    "category": "Judge",
                    "text": "Should nodes be auto-positioned?",
                    "key": 12,
                    "loc": "61 466",
                    "desc": "Should nodes be auto-positioned?",
                    "size": "220 60"
                },
                {
                    "category": "Exec",
                    "text": "Choose a layout",
                    "key": 13,
                    "loc": "61 563",
                    "desc": "Choose a layout",
                    "size": "180 40"
                },
                {
                    "category": "Cancle",
                    "text": "Cancle",
                    "key": 14,
                    "loc": "347 539",
                    "desc": "Cancle",
                    "size": "95 60"
                },
                {
                    "category": "End",
                    "key": 15,
                    "loc": "356 671",
                    "text": "End",
                    "desc": "End",
                    "size": "95 60"
                },
                {
                    "category": "Comment",
                    "text": "GraphLinksModel\nalso allows Groups",
                    "key": 16,
                    "loc": "327 403",
                    "desc": "GraphLinksModel\nalso allows Groups",
                    "size": "155 60"
                }
            ],
            "link": [
                {
                    "from": 1,
                    "to": 6,
                    "text": "提交aaaa",
                    "mmdId": 1,
                    "points": "-122.5,-45,-112.5,-45,-112.5,42,-77,42,-77,-19,3,-19,3,49,3,59",
                    "desc": "提交"
                },
                {
                    "from": 6,
                    "to": 7,
                    "text": "同意",
                    "mmdId": 1,
                    "points": "73,99,83,99,103,99,103,122,123,122,133,122",
                    "desc": "同意"
                },
                {
                    "from": 4,
                    "to": 10,
                    "text": "同意",
                    "mmdId": 1,
                    "points": "-167.5,229,-167.5,239,-167.5,276.5,-176.5,276.5,-176.5,314,-176.5,324",
                    "desc": "同意"
                },
                {
                    "from": 5,
                    "to": 9,
                    "text": "同意",
                    "mmdId": 1,
                    "points": "304,296,294,296,251,296,251,348,208,348,198,348",
                    "desc": "同意"
                },
                {
                    "from": 11,
                    "to": 15,
                    "text": "同意",
                    "mmdId": 1,
                    "points": "196,672,206,672,252.25,672,252.25,671,298.5,671,308.5,671",
                    "desc": "同意"
                },
                {
                    "from": 3,
                    "to": 4,
                    "text": "Yes",
                    "mmdId": 1,
                    "points": "15,259,5,259,-42.5,259,-42.5,199,-90,199,-100,199",
                    "desc": "Yes"
                },
                {
                    "from": 3,
                    "to": 2,
                    "text": "No",
                    "mmdId": 0,
                    "points": "155,259,165,259,164,259,164,259,260,259,260,55,285.5,55,295.5,55",
                    "desc": "No"
                },
                {
                    "from": 7,
                    "to": 3,
                    "text": "同意",
                    "mmdId": 1,
                    "points": "193,162,193,172,193,195.5,85,195.5,85,219,85,229",
                    "desc": "同意"
                },
                {
                    "from": 10,
                    "to": 12,
                    "text": "同意",
                    "mmdId": 1,
                    "points": "-99,374,-89,374,-74,374,-74,466,-59,466,-49,466",
                    "desc": "同意"
                },
                {
                    "from": 9,
                    "to": 12,
                    "text": "同意",
                    "mmdId": 1,
                    "points": "138,388,138,398,138,412,61,412,61,426,61,436",
                    "desc": "同意"
                },
                {
                    "from": 12,
                    "to": 13,
                    "text": "Yes",
                    "mmdId": 1,
                    "points": "61,496,61,506,61,519.5,61,519.5,61,533,61,543",
                    "desc": "Yes"
                },
                {
                    "from": 12,
                    "to": 14,
                    "text": "No",
                    "mmdId": 8,
                    "points": "171,466,181,466,235.25,466,235.25,539,289.5,539,299.5,539",
                    "desc": "No"
                },
                {
                    "from": 13,
                    "to": 8,
                    "text": "同意",
                    "mmdId": 1,
                    "points": "61,583,61,593,61,611.5,-107.5,611.5,-107.5,630,-107.5,640",
                    "desc": "同意"
                },
                {
                    "from": 8,
                    "to": 11,
                    "text": "同意",
                    "mmdId": 1,
                    "points": "-30,670,-20,670,15.5,670,15.5,672,51,672,61,672",
                    "desc": "同意"
                },
                {
                    "from": 2,
                    "to": 5,
                    "text": "重新提交",
                    "mmdId": 2,
                    "points": "345.5,85,345.5,95,345.5,170.5,364,170.5,364,246,364,256",
                    "desc": "重新提交"
                }
            ]
        },
        */
        isEdit: true,
        readonlyEnable: true,  //readonly按钮是否可用
        btnMini: false, //按钮最小化
        beforeBindingTitle: function (callback) {
            callback();
        }, //标题绑定前
        afterBindingTitle: function () { },   //标题绑定后
        getRoleTypeLists: function (lists) {  //获取人员方式
            return lists;
        },
        getRoleMarkModel: function (roleType, pp) {  //人员获取参数
            return pp;
        },
        isEditChange: function (tf) {  //是否可用修改

        }
    };

    $.fn.yqFlowEdit.methods = {
        options: function (jq) {
            return options(jq);
        },
        resize: function (jq, res) {
            var opt = options(jq);
            resize(jq, res);
        },
        isEdit: function (jq, tf) {
            var opt = options(jq);
            if (tf) {
                opt.$isedit.checkbox("uncheck");
            } else {
                opt.$isedit.checkbox("check");
            }            //isEdit(jq, tf);
            //opt.isEditChange.call($object, tf);
        },
        destroy: function (jq) {
            var $object = jq;
            destroy($object);
        },
        setValue: function (jq, val) {
            load(jq, val);
        },
        clear: function (jq) {
            load(jq, {});
        },
        getValue: function (jq) {
            return getModel(jq);
        },
        save: function (jq, filename) {
            saveDiagram(jq, filename);
        },
        load: function (jq) {
            loadFile(jq);
        },
        menuEnable: function (jq, id) {  //按钮可用
            var opt = options(jq);
            opt.$menu.yqTopMenu("enable", id);
        },
        menuDisable: function (jq, id) {  //按钮不可用
            var opt = options(jq);
            opt.$menu.yqTopMenu("disable", id);
        }
    }

    function LoadJsCss(callback) {
        var file = [];
        file.push({ url: "/scripts/gojs/go.js", type: "js" });
        $.yqLoadJsCss(file, function () {
            callback();
        })
    }

    function options($object) {
        return $object.data("flowedit_opt");
    }

    function destroy($object) {
        var opt = options($object);
        var titles = opt.titles;

        $object.empty();
    }

    function resize($object, res) {
        var opt = options($object);
        var $uniqueID = $object.attr("ID");

        if (res === undefined) {
            res = {};
        }

        if (!(res.width === undefined)) {
            opt.width = res.width;
        }
        if (!(res.height === undefined)) {
            opt.height = res.height;
        }

        $object.css({
            "width": (opt.width) + "px",
            "height": (opt.height) + "px"
        });

        var menu_h = opt.$menu.height() ;
        opt.menu_h = menu_h;

        var inner_w = opt.width - 295;
        var inner_h = opt.height - menu_h;
        if(inner_w<200){
            inner_w = 200;
        }
        if(inner_h<200){
            inner_h = 200;
        }

        var $palette = $("#" + $uniqueID + "_palette");
        $palette.parent().css({ "width": inner_w + "px" });
        $palette.css({ "height": inner_h + "px" });
        $palette.find("canvas").height(inner_h);
        $palette.find("div").css({ "height": inner_h + "px" });

        var $diagram = $("#" + $uniqueID + "_diagram");
        $diagram.css({ "height": inner_h + "px" });
        $diagram.find("canvas").height(inner_h);
        $diagram.find("div").css({ "height": inner_h + "px" });

        opt.$itemedit.yqUiMaskEdit("resize", {
            height: inner_h,
            width: 295
        });
    }

    function isEdit($object, tf) {
        var opt = options($object);
        if (tf === undefined) {
            tf = opt.isEdit;
        } else {
            opt.isEdit = tf;
        }

        opt.diagram.clearSelection();
        opt.diagram.grid.visible = tf;
        opt.diagram.isReadOnly = !tf;

        opt.$itemedit.yqUiMaskEdit("isEdit", tf);

        opt.$menu.yqTopMenu(tf ? "enable" : "disable", "index");
        opt.$menu.yqTopMenu(tf ? "enable" : "disable", "clear");
        if (opt._flowstate.node === undefined) {
            opt.$menu.yqTopMenu("disable", "del");
        } else {
            opt.$menu.yqTopMenu(tf ? "enable" : "disable", "del");
        }
    }

    function form_load($object) {
        var opt = options($object);
        isEdit($object);
        resize($object);

        load($object);

        opt.afterBindingTitle.call($object);
    }

    function init_html($object) {
        var opt = options($object);
        var $uniqueID = $object.attr("ID");

        $object.empty();

        var html_ = `
          <table style="width:100%;border-collapse: collapse;border: none;">
          <tr style="background-color: #e7f0ff;">
            <td colspan="2" style="padding:0px;">
              <div id="_uniqueID_menu"></div>
            </td>
            <td style="width: 104px;text-align:right;padding:0px;">
              <input id="_uniqueID_readonly" type="checkbox"/>
            </td>
          </tr>
          <tr>
            <td style="padding:0px;">
              <div style="width: 100%; height: fit-content; display: flex; flex: 2">
                <div id="_uniqueID_palette"
                  style="width: 100px; margin-right: 1px; position: relative; background-color: rgb(20, 30, 55); cursor: auto;">
                </div>
                <div id="_uniqueID_diagram"
                  style="flex-grow: 1; height: 810px; position: relative; background-color: rgb(20, 30, 55); cursor: auto; font: bold 11pt Figtree, sans-serif;">
                </div>
              </div>
            </td>
            <td colspan="2" style="width: 290px;padding:0px;">
                <div id="_uniqueID_itemedit"
                </div>  
            </td>
          </tr>
        </table>
          `;

        html_ = html_.replace(/_uniqueID/g, $uniqueID);
        //console.log(html_);
        $object.append(html_);

        var menus = [{
            id: "index",
            text: "排序",
            iconCls: "yqwin-btn-icon fa fa-arrows",
            onClick: function () {
                orderDiagram($object, $(this));
            }
        }, {
            id: "del",
            text: "删除",
            iconCls: "yqwin-btn-icon fa fa-trash",
            onClick: function () {
                //console.log(opt._flowstate);
                if (opt._flowstate.node === undefined) {
                    return;
                }
                opt.diagram.commandHandler.deleteSelection();

                opt._flowstate = {};
                info_edit($object);
            }
        }, {
            id: "clear",
            text: "清空",
            iconCls: "yqwin-btn-icon fa fa-eraser",
            onClick: function () {
                load($object, {});
                //opt.diagram.clear();
            }
        }];

        if (menus.length > 0) {
            menus.push({});
            for (var i = 0; i < opt.menus.length; i++) {
                menus.push(opt.menus[i]);
            }
        }

        opt.default_theme = "light";
        menus.push(
            {
                id: "print",
                text: "Prn",
                iconCls: "yqwin-btn-icon  fa fa-print",
                onClick: function () {
                    printDiagram($object);
                }
            },
            {
                id: "theme",
                type: "combobox",
                label: "theme",
                labelWidth: 55,
                labelAlign: "left",
                width: 125,
                valueField: 'id',
                textField: 'text',
                data: [{
                    "id": "light",
                    "text": "Light",
                    "selected": true
                }, {
                    "id": "dark",
                    "text": "Dark"
                }],
                onChange: function (newValue, oldValue) {
                    if (opt.diagram) {
                        opt.diagram.themeManager.currentTheme = newValue;
                        var $palette = $("#" + $uniqueID + "_palette");
                        $palette.css({
                            "background-color": "rgb(229, 229, 229)",
                            "box-shadow": "10px 0px 10px -5px rgba(0, 0, 0, 0.5)"
                        });
                    }
                }
            },
            {
                id: "info",
                text: "info",
                iconCls: "yqwin-btn-icon fa fa-info-circle",
                onClick: function () {
                    var prevent_e = $.getPreventDefault(this);
                    prevent_e.id = $object.attr("id");
                    prevent_e.options = {};

                    var w = opt.width - 10;
                    var h = opt.height - opt.menu_h;
                    if (w > 600) {
                        w = 600;
                    }
                    // if (h > 800) {
                    //   h = 800;
                    // }

                    var val = getModel($object);

                    var show_pops = {
                        prevent_e: prevent_e,
                        mdiinfo: $.yqGetWindParams(),
                        width: w,
                        height: h,
                        types: ["json"],
                        //types: ["html"],
                        type: "json",
                        value: JSON.stringify(val, null, 2),
                        isEdit: false,
                        goDocEnd: false,  //加载后，显示在尾部
                        callback: function (value) {
                            //b_value = value;
                        }
                    };
                    if (window.top == window.self) {
                        $.yqCodePopEdit(show_pops);
                    }
                    else {
                        window.top.$.yqCodePopEdit(show_pops);
                    }
                }
            }
        );

        opt.$isedit = $("#" + $uniqueID + "_readonly");

        opt.$isedit.checkbox({
            label: "readonly",
            labelWidth: 80,
            labelPosition: "after",
            checked: (!opt.isEdit),
            onChange: function (checked) {
                isEdit($object, !checked);
                opt.isEditChange.call($object, !checked);
            }
        });

        opt.$menu = $("#" + $uniqueID + "_menu");
        opt.$menu.yqTopMenu({
            menus: menus,
            mini:opt.btnMini,
            afterBindingTitle: function () {
                init_flow($object);
            },
        });
    }

    function init_flow($object) {
        var opt = options($object);
        var $uniqueID = $object.attr("ID");

        opt.$ = go.GraphObject.make;

        opt.diagram = new go.Diagram(
            $uniqueID + '_diagram',
            {
                'undoManager.isEnabled': true,
                'themeManager.changesDivBackground': true,
                'themeManager.currentTheme': opt.default_theme,
                "grid": opt.$(go.Panel,
                    'Grid',
                    opt.$(go.Shape, 'LineH', {
                        stroke: 'lightgray',
                        strokeWidth: 0.5
                    }),
                    opt.$(go.Shape, 'LineV', {
                        stroke: 'lightgray',
                        strokeWidth: 0.5
                    })
                ),
                "click": function (e) {
                    info_edit($object);
                },
            }
        );

        // when the document is modified
        opt.diagram.addDiagramListener('Modified', (e) => {

        });

        opt.diagram.themeManager.set('light', {
            colors: {
                text: '#fff',
                start: '#064e3b',
                return: '#669933',
                exec: '#49939e',
                proc: '#0066CC',
                judge: '#6a9a8a',
                end: '#7f1d1d',
                cancle: '#FF9900',
                comment: '#a691cc',
                bgText: '#000',
                link: '#dcb263',
                linkOver: '#cbd5e1',
                div: '#ffffff',
            },
        });

        opt.diagram.themeManager.set('dark', {
            colors: {
                text: '#fff',
                start: '#064e3b',
                return: '#669933',
                exec: '#414a8d',
                proc: '#0066CC',
                judge: '#88afa2',
                cancle: '#FF9900',
                comment: '#bfb674',
                bgText: '#fff',
                link: '#fdb71c',
                linkOver: '#475569',
                div: '#141e37',
            },
        });

        defineFigures();

        //节点类型
        function nodeStyle_flow(node, s_type) {
            node
                .set({
                    locationSpot: go.Spot.Center,
                    locationObjectName: 'SHAPE',
                    desiredSize: new go.Size(75, 40),
                    minSize: new go.Size(40, 40),
                    resizable: true,
                    resizeCellSize: new go.Size(20, 20),
                })
                .bindTwoWay('desiredSize', 'size', go.Size.parse, go.Size.stringify)
                .bindTwoWay('location', 'loc', go.Point.parse, go.Point.stringify);
        }
        //节点选择
        function selectionChanged_flow(node, s_type) {
            if (!(node.data.model === undefined)) {
                return;
            }

            if (s_type === undefined) {
                s_type = 9001;
            }

            if (node.isSelected) {
                opt._flowstate = {
                    node: node,
                    type: s_type
                };
                var nodeData = node.data;
                opt.$itemedit.yqUiMaskEdit("setValue", { ui_type: s_type, value: nodeData });

                opt.$menu.yqTopMenu(opt.isEdit ? "enable" : "disable", "del");
            } else {
                //console.log(s_type + "-unselelct");
                opt._flowstate = {
                };

                opt.$menu.yqTopMenu("disable", "del");
            }
        }

        function shapeStyle(shape) {
            shape.set({
                strokeWidth: 0,
                portId: '',
                cursor: 'pointer',
            });
        }

        function textStyle(textblock) {
            textblock
                .set({
                    font: 'bold 11pt Figtree, sans-serif',
                    cursor: "all-scroll",
                })
                .theme('stroke', 'text');
        }

        opt.diagram.nodeTemplateMap.add(
            'Exec',
            new go.Node('Auto').apply(nodeStyle_flow)
                .set({
                    selectionChanged: function (node) {
                        selectionChanged_flow(node, 9005);
                    },

                }).add(
                    new go.Shape('Rectangle', {
                        fromLinkable: true,
                        toLinkable: true,
                        fromSpot: go.Spot.AllSides,
                        toSpot: go.Spot.AllSides,
                    })
                        .apply(shapeStyle)
                        .theme('fill', 'exec'),

                    new go.Picture({
                        source: "",
                        margin: 0,
                        desiredSize: new go.Size(24, 24),
                        alignment: go.Spot.TopRight,
                    }),

                    new go.TextBlock({
                        //background: "#95b8e7",
                        margin: 12,
                        //maxSize: new go.Size(160, NaN),
                        wrap: go.Wrap.Fit,
                        //editable: true,
                    })
                        .apply(textStyle)
                        .bindTwoWay('text')
                )
        );

        opt.diagram.nodeTemplateMap.add(
            'Proc',
            new go.Node('Auto').apply(nodeStyle_flow)
                .set({
                    selectionChanged: function (node) {
                        selectionChanged_flow(node, 9007);
                    }
                }).add(
                    new go.Shape('Rectangle', {
                        fromLinkable: true,
                        toLinkable: true,
                        fromSpot: go.Spot.AllSides,
                        toSpot: go.Spot.AllSides,
                    })
                        .apply(shapeStyle)
                        .theme('fill', 'proc'),

                    new go.Picture({
                        source: "",
                        margin: 0,
                        desiredSize: new go.Size(24, 24),
                        alignment: go.Spot.TopRight,
                    }),

                    new go.TextBlock({
                        margin: 12,
                        //maxSize: new go.Size(160, NaN),
                        wrap: go.Wrap.Fit,
                        //editable: true,
                    })
                        .apply(textStyle)
                        .bindTwoWay('text')
                )
        );

        opt.diagram.nodeTemplateMap.add(
            'Judge',
            new go.Node('Auto').apply(nodeStyle_flow)
                .set({
                    selectionChanged: function (node) {
                        selectionChanged_flow(node, 9006);
                    }
                }).add(
                    new go.Shape('Judge', {
                        fromLinkable: true,
                        toLinkable: true
                    }).apply(shapeStyle).theme('fill', 'judge'),
                    new go.TextBlock({
                        margin: 8,
                        //maxSize: new go.Size(160, NaN),
                        wrap: go.Wrap.Fit,
                        textAlign: 'center',
                        //editable: true,
                    })
                        .apply(textStyle)
                        .bindTwoWay('text')
                )
        );

        opt.diagram.nodeTemplateMap.add(
            'Start',
            new go.Node('Auto')
                .apply(nodeStyle_flow)
                .set({
                    selectionChanged: function (node) {
                        selectionChanged_flow(node, 9001);
                    }
                })
                .add(
                    new go.Shape('Capsule', {
                        fromLinkable: true
                    }).apply(shapeStyle).theme('fill', 'start'),
                    new go.TextBlock('Start', {
                        margin: new go.Margin(5, 6)
                    }).apply(textStyle).bind('text')
                )
        );

        opt.diagram.nodeTemplateMap.add(
            'Return',
            new go.Node('Auto')
                .apply(nodeStyle_flow)
                .set({
                    selectionChanged: function (node) {
                        selectionChanged_flow(node, 9002);
                    }
                })
                .add(
                    new go.Shape('Capsule', {
                        fromLinkable: true,
                        toLinkable: true
                    }).apply(shapeStyle).theme('fill', 'return'),
                    new go.TextBlock('Return', {
                        margin: new go.Margin(5, 6)
                    }).apply(textStyle).bind('text')
                )
        );

        opt.diagram.nodeTemplateMap.add(
            'End',
            new go.Node('Auto')
                .apply(nodeStyle_flow)
                .set({
                    selectionChanged: function (node) {
                        selectionChanged_flow(node, 9009);
                    }
                })
                .add(
                    new go.Shape('Capsule', {
                        toLinkable: true
                    }).apply(shapeStyle).theme('fill', 'end'),
                    new go.TextBlock('End', {
                        margin: new go.Margin(5, 6)
                    }).apply(textStyle).bind('text')
                )
        );

        opt.diagram.nodeTemplateMap.add(
            'Cancle',
            new go.Node('Auto')
                .apply(nodeStyle_flow)
                .set({
                    selectionChanged: function (node) {
                        selectionChanged_flow(node, 9008);
                    }
                })
                .add(
                    new go.Shape('Capsule', {
                        toLinkable: true
                    }).apply(shapeStyle).theme('fill', 'cancle'),
                    new go.TextBlock('Cancle', {
                        margin: new go.Margin(5, 6)
                    }).apply(textStyle).bind('text')
                )
        );

        opt.diagram.nodeTemplateMap.add(
            'Comment',
            new go.Node('Auto').apply(nodeStyle_flow)
                .set({
                    selectionChanged: function (node) {
                        selectionChanged_flow(node, 9010);
                    }
                })
                .add(
                    new go.Shape('File', {
                        strokeWidth: 3,
                        stretch: go.GraphObject.Fill // 确保 Shape 的宽度跟随 Node 的宽度
                    })
                        .theme('fill', 'div').theme('stroke', 'comment'),

                    // 使用 Panel 将两个 TextBlock 垂直排列
                    new go.Panel('Vertical', {
                        margin: new go.Margin(2, 5, 5, 5),
                        stretch: go.GraphObject.Fill
                    }).add(
                        new go.TextBlock({     // 显示 text
                            font: 'bold 11pt Figtree, sans-serif',
                            lineSpacing: 6,
                            margin: new go.Margin(0, 0, 8, 0),
                            wrap: go.Wrap.Fit,
                            isMultiline: false,   // 设置为单行文本
                            textAlign: 'center'
                        })
                            .bindTwoWay('text'),
                        new go.TextBlock({   // 显示 desc
                            font: '9pt Figtree, sans-serif',
                            lineSpacing: 16, // 设置行间距为 6
                            margin: new go.Margin(2, 0),
                            wrap: go.Wrap.Fit,
                            isMultiline: true,
                            textAlign: 'start'
                        })
                            .bindTwoWay('text', 'desc')
                            .bind("visible", function (data) {
                                var visible = true;
                                if (data.desc === undefined || data.desc == "") {
                                    visible = false;
                                }
                                return visible;
                            })
                    )
                )
        );

        //连线
        opt.diagram.linkTemplate = new go.Link({
            routing: go.Routing.AvoidsNodes,
            curve: go.Curve.JumpOver,
            corner: 5,
            toShortLength: 4,
            relinkableFrom: true,
            relinkableTo: true,
            reshapable: true,
            resegmentable: true,
            mouseEnter: (e, link) => (link.findObject('HIGHLIGHT').stroke = link.diagram.themeManager.findValue('linkOver', 'colors')),
            mouseLeave: (e, link) => (link.findObject('HIGHLIGHT').stroke = 'transparent'),
            contextClick: (e, link) => {
                e.diagram.model.commit((m) => {
                    m.set(link.data, 'text', 'Label');
                });
            },
            selectionChanged: function (line) {
                var nodeData = line.data;
                //console.log(nodeData);
                var s_type = 9099;
                if (line.isSelected) {
                    opt._flowstate = {
                        node: line,
                        type: s_type
                    };

                    opt.$itemedit.yqUiMaskEdit("setValue", { ui_type: s_type, value: nodeData });

                    opt.$menu.yqTopMenu(opt.isEdit ? "enable" : "disable", "del");
                } else {
                    opt._flowstate = {
                    };

                    opt.$menu.yqTopMenu("disable", "del");
                }
            },
            fromPortChanged: function (thisLink, oldPort, newPort) {
                linkPortChanged(thisLink);
            },
            toPortChanged: function (thisLink, oldPort, newPort) {
                linkPortChanged(thisLink);
            }
        })
            //.bindTwoWay('points')
            .bindTwoWay('points')
            .add(
                new go.Shape({
                    isPanelMain: true,
                    strokeWidth: 8,
                    stroke: 'transparent',
                    name: 'HIGHLIGHT',
                }),
                new go.Shape({ isPanelMain: true, strokeWidth: 2 }).theme('stroke', 'link'),
                new go.Shape({ toArrow: 'standard', strokeWidth: 0, scale: 1.5 }).theme('fill', 'link'),
                new go.Panel('Auto', { visible: false })
                    .bind('visible', 'text', (t) => typeof t === 'string' && t.length > 0) // only shown if there is text
                    .add(
                        new go.Shape('Ellipse', { strokeWidth: 0 }).theme('fill', 'div', null, null, (c) => {
                            return new go.Brush(go.BrushType.Radial, {
                                colorStops: new go.Map([
                                    { key: 0, value: c },
                                    { key: 0.5, value: `${c}00` },
                                ]),
                            });
                        }),
                        new go.TextBlock({
                            name: 'LABEL',
                            font: '9pt Figtree, sans-serif',
                            margin: 3,
                            editable: true,
                        })
                            .theme('stroke', 'bgText')
                            .bindTwoWay('text')
                    )
            );

        function linkPortChanged(link) {
            var data = link.data;
            var node_f = opt.diagram.findNodeForKey(data.from);
            var node_t = opt.diagram.findNodeForKey(data.to);

            if (node_f.category == "Start") {  //开始节点
                if (data.text === undefined) {
                    opt.diagram.model.setDataProperty(data, "text", "提交");
                }
                opt.diagram.model.setDataProperty(data, "mmdId", 1);
            }
            else if (node_f.category == "Return") {   //退回节点
                if (data.text === undefined) {
                    opt.diagram.model.setDataProperty(data, "text", "重新提交");
                }
                opt.diagram.model.setDataProperty(data, "mmdId", 2);
            }
            else if (node_t.category == "Return") {
                if (data.text === undefined) {
                    opt.diagram.model.setDataProperty(data, "text", "退回");
                }
                opt.diagram.model.setDataProperty(data, "mmdId", 0);
            }
            else if (node_t.category == "End") {
                if (data.text === undefined) {
                    opt.diagram.model.setDataProperty(data, "text", "同意");
                }
                opt.diagram.model.setDataProperty(data, "mmdId", 1);
            }
            else if (node_t.category == "Cancle") {
                if (data.text === undefined) {
                    opt.diagram.model.setDataProperty(data, "text", "取消");
                }
                opt.diagram.model.setDataProperty(data, "mmdId", 8);
            } else {
                if (data.text === undefined) {
                    opt.diagram.model.setDataProperty(data, "text", "同意");
                }
                opt.diagram.model.setDataProperty(data, "mmdId", 1);
            }
        }

        opt.diagram.toolManager.linkingTool.temporaryLink.routing = go.Routing.Orthogonal;
        opt.diagram.toolManager.relinkingTool.temporaryLink.routing = go.Routing.Orthogonal;

        //opt.diagram.model = go.Model.fromJson(jsonVal);

        opt.palette = new go.Palette(
            $uniqueID + '_palette',
            {
                nodeTemplateMap: opt.diagram.nodeTemplateMap,
                themeManager: opt.diagram.themeManager,
                model: new go.GraphLinksModel([
                    { category: 'Start', text: 'Start' },
                    { category: 'Return', text: 'Return' },
                    { category: 'Exec', text: 'Exec' },
                    { category: 'Proc', text: 'Proc' },
                    { category: 'Judge', text: '???' },
                    { category: 'End', text: 'End' },
                    { category: 'Cancle', text: 'Cancle' },
                    { category: 'Comment', text: 'Txt' },
                ]),
            }
        );

        var $palette = $("#" + $uniqueID + "_palette");
        $palette.css({
            "background-color": "rgb(229, 229, 229)",
            "box-shadow": "10px 0px 10px -5px rgba(0, 0, 0, 0.5)"
        });

        init_itemedit($object);
    }

    function defineFigures() {
        go.Shape.defineFigureGenerator('Judge', (shape, w, h) => {
            const geo = new go.Geometry();
            const fig = new go.PathFigure(w * 0.15, 0, true);
            geo.add(fig);
            fig.add(new go.PathSegment(go.SegmentType.Line, w * 0.85, 0));
            fig.add(new go.PathSegment(go.SegmentType.Line, w, 0.5 * h));
            fig.add(new go.PathSegment(go.SegmentType.Line, w * 0.85, h));
            fig.add(new go.PathSegment(go.SegmentType.Line, w * 0.15, h));
            fig.add(new go.PathSegment(go.SegmentType.Line, 0, 0.5 * h).close());
            geo.spot1 = new go.Spot(0.15, 0);
            geo.spot2 = new go.Spot(0.85, 1);
            return geo;
        });

        go.Shape.defineFigureGenerator('File', (shape, w, h) => {
            const geo = new go.Geometry();
            const fig = new go.PathFigure(0, 0, true);
            geo.add(fig);

            var w_ = (w > 100 ? (w - 40) : 0.75 * w);
            var h_ = (h > 50 ? 20 : 0.25 * h);

            fig.add(new go.PathSegment(go.SegmentType.Line, w_, 0));
            fig.add(new go.PathSegment(go.SegmentType.Line, w, h_));
            fig.add(new go.PathSegment(go.SegmentType.Line, w, h));
            fig.add(new go.PathSegment(go.SegmentType.Line, 0, h).close());
            const fig2 = new go.PathFigure(w_, 0, false);
            geo.add(fig2);
            // The Fold
            fig2.add(new go.PathSegment(go.SegmentType.Line, w_, h_));
            fig2.add(new go.PathSegment(go.SegmentType.Line, w, h_));
            geo.spot1 = new go.Spot(0, 0.25);
            geo.spot2 = go.Spot.BottomRight;
            return geo;
        });
    }

    function init_itemedit($object) {
        var opt = options($object);
        var $uniqueID = $object.attr("ID");
        opt.$itemedit = $("#" + $uniqueID + "_itemedit");

        opt.$itemedit.yqUiMaskEdit({
            ui_type: 2,  //ui类型
            value: {},
            isEdit: true,
            treeEdit: false,
            //自定义数据格式接口
            columns: [
                {
                    field: 'name', title: '名称', width: '40%'
                }, {
                    field: 'value',
                    title: '值',
                    width: '45%',
                }
            ],
            defaultAdd: false,
            afterBindingTitle: function () {
                init_jsonview($object);
            },
            uiMaskLoadInit: function (ui_type, value, data) {
                return itemedit_loadInit($object, ui_type, value);
            },
            endEdit: function (index, row) {
                console.log("endEdit", index, row);
                var s_type = opt.$itemedit.yqUiMaskEdit("getUiType");
                if (s_type === 9000) {
                    opt.value.info[row.field] = row.value;
                } else {
                    var node = opt._flowstate.node;
                    opt.diagram.model.setDataProperty(node.data, row.field, row.value);
                    if (row.field == "roleType") {
                        var s_type = opt.$itemedit.yqUiMaskEdit("getUiType");
                        var nodeData = opt.$itemedit.yqUiMaskEdit("getValue");
                        opt.$itemedit.yqUiMaskEdit("setValue", { ui_type: s_type, value: nodeData });

                        //console.log(s_type, nodeData);
                    }
                }
            },
        });
    }

    //基础信息编辑
    function info_edit($object) {
        var opt = options($object);
        var data_ = opt.value.info;
        if (data_ === undefined) {
            data_ = {};
            opt.value.info = data_;
        }

        opt.$itemedit.yqUiMaskEdit("setValue", { ui_type: 9000, value: data_ });

        if (opt.$menu) {
            opt.$menu.yqTopMenu("disable", "del");
        }
    }

    /*
         主信息：              class
             9000 主信息    
         点：
             9001 开始节点  1
             9002 退回节点  2
 
             9005 执行节点  5
             9007 程序节点  7
             9006 判断节点  6
 
             9008 取消节点  8
             9009 结束节点  9
 
             9010 文档节点
         线
             9099 线
     */
    function itemedit_loadInit($object, ui_type, value) {
        var opt = options($object);
        //console.log(ui_type, value);

        var data;

        if (ui_type == 9000) {  // 基础信息
            data = {
                "rows": [
                    $.yqDgEditor({
                        field: "ver",
                        name: "版本",
                        value: "",
                        group: "流程信息"
                    }, 10, {
                        readonly: false,
                        default: 1,
                        blank: false,
                        min: 1
                    }),
                    $.yqDgEditor({
                        field: "current",
                        name: "当前版本",
                        value: "",
                        group: "流程信息"
                    }, 3, {
                        readonly: false,
                        default: true
                    }),
                    $.yqDgEditor({
                        field: "name",
                        name: "名称",
                        value: "",
                        group: "流程信息"
                    }, 2, {
                        readonly: false
                    }),
                    $.yqDgEditor({
                        field: "describe",
                        name: "描述",
                        value: "",
                        group: "流程信息"
                    }, 5, {
                        readonly: false
                    }),
                    $.yqDgEditor({
                        field: "case_when",
                        name: "条件（,分隔）",
                        value: "",
                        group: "流程信息"
                    }, 2, {
                        readonly: false
                    }),

                    $.yqDgEditor({
                        field: "remark",
                        name: "备注",
                        value: null,
                        group: "流程信息"
                    }, 5, {
                        readonly: false
                    }),

                    $.yqDgEditor({
                        field: "func",
                        name: "程序地址",
                        value: "",
                        group: "接口信息"
                    }, 2, {
                        readonly: false
                    }),
                    $.yqDgEditor({
                        field: "db_name",
                        name: "数据库",
                        value: "",
                        group: "接口信息"
                    }, 2, {
                        readonly: false
                    }),
                    $.yqDgEditor({
                        field: "tb_name",
                        name: "表",
                        value: "",
                        group: "接口信息"
                    }, 2, {
                        readonly: false
                    }),
                    $.yqDgEditor({
                        field: "state_field",
                        name: "状态字段",
                        value: "",
                        group: "接口信息"
                    }, 2, {
                        readonly: false
                    }),
                    $.yqDgEditor({
                        field: "state_func",
                        name: "状态程序",
                        value: "",
                        group: "接口信息"
                    }, 2, {
                        readonly: false
                    }),
                    $.yqDgEditor({
                        field: "state_start",
                        name: "发起状态",
                        value: "",
                        group: "接口信息"
                    }, 2, {
                        readonly: false
                    }),
                    $.yqDgEditor({
                        field: "state_start_name",
                        name: "状态名称",
                        value: "",
                        group: "接口信息"
                    }, 2, {
                        readonly: false
                    }),
                    $.yqDgEditor({
                        field: "params",
                        name: "全局参数",
                        value: null,
                        group: "接口信息"
                    }, 15, {
                        "editModeW": 650,
                        "editModeH": 400,
                        "param": {
                            "titles": [
                                {
                                    "is_func": false,
                                    "name": "name",
                                    "ui_title": "参数名称",
                                    "ui_type": 2,
                                    "ui_width": 80,
                                    "ui_visible": true,
                                    "ui_readonly": false,
                                    "ui_mask": {}
                                },
                                {
                                    "is_func": false,
                                    "name": "desc",
                                    "ui_title": "参数描述",
                                    "ui_type": 2,
                                    "ui_width": 120,
                                    "ui_visible": true,
                                    "ui_readonly": false,
                                    "ui_mask": {}
                                }, {
                                    "is_func": false,
                                    "name": "type",
                                    "ui_title": "数据类型",
                                    "ui_type": 6,
                                    "ui_width": 110,
                                    "ui_visible": true,
                                    "ui_readonly": false,
                                    "ui_mask": {
                                        "default": 1,
                                        "blank": false,
                                        "lists": $.yqUiTypes()
                                    }
                                }, {
                                    "is_func": false,
                                    "name": "ui_mask",
                                    "ui_title": "ui掩码",
                                    "ui_type": 900,
                                    "ui_width": 100,
                                    "ui_visible": true,
                                    "ui_readonly": false,
                                    "ui_mask": {
                                        pop_edit: true,
                                        editModeW: 500,
                                        editModeH: 400,
                                        blank: false,
                                        beforeEditShow: function (run_opt) {
                                            var $edit = $(this).closest(".datagrid-row").find('td[field="type"]').find('.combobox-f');
                                            var ui_type = $edit.combobox("getValue");
                                            run_opt.ui_type = ui_type;
                                            return run_opt;
                                        },
                                    }
                                }, {
                                    "is_func": false,
                                    "name": "source_type",
                                    "ui_title": "数据来源类型",
                                    "ui_type": 6,
                                    "ui_width": 110,
                                    "ui_visible": true,
                                    "ui_readonly": false,
                                    "ui_mask": {
                                        "default": 1,
                                        "blank": false,
                                        "lists": [
                                            {
                                                "no": 1,
                                                "name": "输入"
                                            },
                                            {
                                                "no": 2,
                                                "name": "流程表单"
                                            },
                                            {
                                                "no": 3,
                                                "name": "接口程序"
                                            }
                                        ]
                                    }
                                }, {
                                    "name": "source",
                                    "ui_title": "数据来源",
                                    "ui_type": 17,
                                    "ui_width": 80,
                                    "ui_visible": true,
                                    "ui_readonly": false,
                                    "ui_mask": {
                                        "default": {},
                                        "editType": 1,
                                        "editModeW": 500,
                                        "editModeH": 200,
                                        "modelNo": 1,
                                        "removeUnUse": true,
                                        "param": {
                                            "titles": []
                                        },
                                        beforeEditShow: function (run_opt) {
                                            var $edit = $(this).closest(".datagrid-row").find('td[field="source_type"]').find('.combobox-f');
                                            var source_type = $edit.combobox("getValue");
                                            //console.log(source_type);
                                            //console.log("beforeEditShow",$edit, run_opt);
                                            run_opt.titles = getFlowInputParam(source_type);
                                            return run_opt;
                                        },
                                    }
                                },
                            ],
                            "model": []
                        }
                    }),

                    $.yqDgEditor({
                        field: "parameter",
                        name: "测试参数",
                        value: "",
                        group: "测试"
                    }, 17, {
                        "editModeW": 400,
                        "editModeH": 200,
                        "param": {
                            "titles": [
                                {
                                    "name": "org_id",
                                    "ui_title": "部门",
                                    "ui_type": 7,
                                    "ui_width": 220,
                                    "ui_visible": true,
                                    "ui_readonly": false,
                                    "ui_mask": {
                                        "blank": false,
                                        "dbName": "yqbase",
                                        "tbName": "hr_org",
                                        "tempNo": 100,
                                        "displayType": 2,
                                        "valueMember": "sid",
                                        "displayMember": "name",
                                        "isPage": true,
                                        "pageSize": 10,
                                        "order": "t_path",
                                        "panelWidth": 550,
                                        "panelHeight": 400,
                                        "seekSimple": true,
                                        "seekSimpleDDLW": 120,
                                        "seekSimpleTxtW": 150,
                                        "isSeek": true,
                                        "seekNo": -1,
                                        "seekModeW": 800,
                                        "seekModeH": 600
                                    }
                                },
                                {
                                    "name": "user_id",
                                    "ui_title": "人员",
                                    "ui_type": 7,
                                    "ui_width": 180,
                                    "ui_visible": true,
                                    "ui_readonly": false,
                                    "ui_mask": {
                                        "blank": false,
                                        "dbName": "yqbase",
                                        "tbName": "hr_user",
                                        "tempNo": 100,
                                        "displayType": 2,
                                        "valueMember": "sid",
                                        "displayMember": "name",
                                        "isPage": true,
                                        "pageSize": 10,
                                        "order": "name",
                                        "panelWidth": 550,
                                        "panelHeight": 400,
                                        "seekSimple": true,
                                        "seekSimpleDDLW": 120,
                                        "seekSimpleTxtW": 150,
                                        "isSeek": true,
                                        "seekNo": -1,
                                        "seekModeW": 800,
                                        "seekModeH": 600
                                    }
                                }
                            ],
                            "model": []
                        }
                    }),

                    /*
                    $.yqDgEditor({
                        field: "foreignkey",
                        name: "foreignkey",
                        value: "",
                        group: "测试"
                    }, 7, {
                        "default": null,
                        "blank": true,
                        "dbName": "yqbase",
                        "tbName": "ab_test_m",
                        "tempNo": -1,
                        "displayType": 2,
                        "valueMember": "sid",
                        "displayMember": "textbox",
                        "isPage": true,
                        "pageSize": 10,
                        "addWhere": "",
                        "order": "textbox",
                        "panelWidth": 600,
                        "panelHeight": 460,
                        "expandMember": null,
                        "seekNo": -1,
                        "seekModeW": 800,
                        "seekModeH": 600,
                        "mapping": [
                            {
                                "from": "textbox",
                                "to": "foreignkeyVal"
                            }]
                    }), $.yqDgEditor({
                        field: "foreignkeyVal",
                        name: "foreignkeyVal",
                        value: "",
                        group: "测试"
                    }, 2, {})
                    */
                ]
            };
        }
        else if (ui_type == 9099) {
            data = {
                "rows": [
                    $.yqDgEditor({
                        field: "text",
                        name: "text",
                        value: "",
                        group: "连线描述"
                    }, 2, {
                        readonly: false
                    }),
                    $.yqDgEditor({
                        field: "desc",
                        name: "desc",
                        value: "",
                        group: "连线描述"
                    }, 5, {
                        readonly: false
                    }),
                    $.yqDgEditor({
                        field: "remark",
                        name: "remark",
                        value: null,
                        group: "连线描述"
                    }, 5, {
                        readonly: false
                    })
                ]
            };
        }
        else {
            data = {
                "rows": [$.yqDgEditor({
                    field: "category",
                    name: "category",
                    value: "",
                    group: "基础信息"
                }, 2, {
                    readonly: true
                }),
                $.yqDgEditor({
                    field: "key",
                    name: "key",
                    value: -1,
                    group: "基础信息"
                }, 10, {
                    min: -1,
                    readonly: true
                }),
                $.yqDgEditor({
                    field: "loc",
                    name: "loc",
                    value: "",
                    group: "基础信息"
                }, 2, {
                    readonly: true
                }),
                $.yqDgEditor({
                    field: "text",
                    name: "名称",
                    value: "",
                    group: "节点描述"
                }, 2, {
                    readonly: false
                }),
                $.yqDgEditor({
                    field: "desc",
                    name: "描述",
                    value: "",
                    group: "节点描述"
                }, 5, {
                    readonly: false
                }),
                $.yqDgEditor({
                    field: "remark",
                    name: "备注",
                    value: null,
                    group: "节点描述"
                }, 5, {
                    readonly: false
                })
                ]
            };
        }

        if (ui_type == 9002 || ui_type == 9005 || ui_type == 9007 || ui_type == 9009 || ui_type == 9008) {
            data.rows.push($.yqDgEditor({
                field: "state",
                name: "state",
                value: null,
                group: "到达状态"
            }, 10, {
                min: -1,
                readonly: false
            }));

            data.rows.push($.yqDgEditor({
                field: "stateName",
                name: "s_name",
                value: "",
                group: "到达状态"
            }, 2, {
                readonly: false
            }));
        }

        //人工执行节点
        if (ui_type == 9005) {
            data.rows.push($.yqDgEditor({
                field: "code",
                name: "编码",
                value: "",
                group: "节点描述"
            }, 2, {
                readonly: false
            }));

            var roleTypeLists = opt.getRoleTypeLists.call($object, [
                { "no": "1", "name": "发起人" },
                { "no": "2", "name": "指定人员" },
                { "no": "3", "name": "指定岗位" },
                { "no": "4", "name": "指定部门+职位" },
                { "no": "5", "name": "发起人部门+职位" },
                { "no": "99", "name": "按代码" }]);

            var roleType = -1;
            if (!(value["roleType"] === undefined)) {
                roleType = parseInt(value["roleType"]);
            }

            data.rows.push($.yqDgEditor({
                field: "roleType",
                name: "获取人员方式",
                value: -1,
                group: "审批方式"
            }, 6, {
                default: 2,
                lists: roleTypeLists,
                readonly: false
            }));

            var pp2 = opt.getRoleMarkModel.call($object, roleType, getRoleMarkModel(roleType));
            data.rows.push(pp2);

            data.rows.push($.yqDgEditor({
                field: "roleIsEdit",
                name: "人员变更",
                value: "",
                group: "审批方式"
            }, 3, {
                readonly: false
            }));

            data.rows.push($.yqDgEditor({
                field: "rolePass",
                name: "自动审批",
                value: "",
                group: "审批方式"
            }, 3, {
                readonly: false
            }));

            data.rows.push($.yqDgEditor({
                field: "duplicateType",
                name: "通过方式",
                value: -1,
                group: "审批方式"
            }, 6, {
                default: 1,
                lists: [
                    { "no": "1", "name": "单人审批" },
                    { "no": "2", "name": "最小通过人数" },
                    { "no": "3", "name": "最小通过百分比" },
                    { "no": "4", "name": "全部通过" }],
                readonly: false
            }));

            data.rows.push($.yqDgEditor({
                field: "duplicateNum",
                name: "审批阀值",
                value: null,
                group: "审批方式"
            }, 10, {
                min: -1,
                readonly: false
            }));
        }
        else if (ui_type == 9007) {
            var node = opt._flowstate.node;
            //var node = opt.diagram.findNodeForKey(value.key);
            var lines = node.findLinksOutOf();
            console.log("lines", lines.count);
            var lists_ = [];
            if (lines.count == 0) {
                opt.diagram.model.setDataProperty(node.data, "type", 1);
                lists_ = [{ "no": "1", "name": "消息" }];
            } else {
                opt.diagram.model.setDataProperty(node.data, "type", 2);
                lists_ = [{ "no": "2", "name": "审批" }];
            }

            data.rows.push($.yqDgEditor({
                field: "type",
                name: "类型",
                value: -1,
                group: "程序"
            }, 6, {
                default: 1,
                lists: lists_,
                readonly: true
            }));

            data.rows.push($.yqDgEditor({
                field: "url",
                name: "接口地址",
                value: "",
                group: "程序"
            }, 5, {
                readonly: false
            }));
        }
        else if (ui_type == 9099) {
            var node_f = opt.diagram.findNodeForKey(value.from);
            var node_t = opt.diagram.findNodeForKey(value.to);

            var lists = [];
            //开始节点
            if (node_f.category == "Start") {
                lists = [{ "no": 1, "name": "提交" }];
            }
            //退回节点
            else if (node_f.category == "Return") {
                lists = [{ "no": 2, "name": "重新提交" }];
            }
            else if (node_t.category == "Return") {
                lists = [{ "no": 0, "name": "退回" }];
            }
            else if (node_t.category == "End") {
                lists = [{ "no": 1, "name": "同意" }];
            }
            else if (node_t.category == "Cancle") {
                lists = [{ "no": 8, "name": "取消" }];
            } else {
                lists = [{ "no": 1, "name": "同意" }, { "no": 0, "name": "不同意" }];
            }

            console.log("node_f", node_f, node_f.category);

            if (node_f.category != "Judge") {
                data.rows.unshift(...[$.yqDgEditor({
                    field: "mmdId",
                    name: "操作类型",
                    value: lists[0].no,
                    group: "操作类型"
                }, 6, {
                    default: 1,
                    lists: lists,
                    readonly: (lists.length == 1 ? true : false)
                })]);
            }

            data.rows.push($.yqDgEditor({
                field: "expression",
                name: "执行逻辑",
                value: "",
                group: "执行逻辑"
            }, 5, {
                readonly: false
            }));
        }

        //提交参数
        if (ui_type == 9001 || ui_type == 9002 || ui_type == 9005) {
            var params = opt.value.info.params;
            if (params === undefined || params === null) {
                params = [];
            }

            //console.log(params);
            var lists = [];
            for (var i = 0; i < params.length; i++) {
                if (params[i].source_type == 1) {
                    lists.push({
                        "no": params[i].name,
                        "name": params[i].desc
                    });
                }
            }

            data.rows.push($.yqDgEditor({
                field: "params",
                name: "全局参数",
                value: null,
                group: "提交参数"
            }, 15, {
                readonly: false,
                editModeW: 400,
                editModeH: 280,
                editType: 0,
                param: {
                    titles: [
                        {
                            name: "name",
                            ui_title: "参数",
                            ui_type: 6,
                            ui_width: 130,
                            ui_visible: true,
                            ui_readonly: false,
                            ui_mask: {
                                type: "string",
                                default: "",
                                lists: lists,
                                onChange: function (target, value) {
                                    var desc;
                                    if (value != "") {
                                        desc = $(this).combobox("getText");
                                    }
                                    var $desc = $(this).closest(".datagrid-row").find('td[field="desc"]').find('.textbox-f');
                                    $desc.textbox("setValue", desc);
                                }
                            }
                        },
                        {
                            name: "desc",
                            ui_title: "参数描述",
                            ui_type: 2,
                            ui_width: 200,
                            ui_visible: true,
                            ui_readonly: false,
                            ui_mask: {}
                        }
                    ],
                    model: []
                }
            }));
        }

        return data;
    }

    //获取流程输入参数
    function getFlowInputParam(source_type) {
        var titles = [];

        if (source_type == 1) {   //输入
            titles = [
            ];
        } else if (source_type == 2) {   //流程表单
            titles = [{
                "is_func": false,
                "name": "mapField",
                "ui_title": "拷贝字段",
                "ui_type": 2,
                "ui_width": 100,
                "ui_visible": true,
                "ui_readonly": false,
                "ui_mask": {}
            },
            {
                "is_func": false,
                "name": "mapDesc",
                "ui_title": "字段描述",
                "ui_type": 2,
                "ui_width": 100,
                "ui_visible": true,
                "ui_readonly": false,
                "ui_mask": {}
            }];
        }
        else if (source_type == 3) {   //接口程序
            titles = [{
                "is_func": false,
                "name": "funcName",
                "ui_title": "程序名称",
                "ui_type": 2,
                "ui_width": 100,
                "ui_visible": true,
                "ui_readonly": false,
                "ui_mask": {}
            }];
        }

        return titles;
    }

    //人员获取参数模版
    function getRoleMarkModel(roleType) {
        var pp;

        var title = {
            field: "roleMark",
            name: "人员获取参数",
            value: "",
            group: "审批方式"
        };

        if (roleType == 1) {  //发起人
            pp = $.yqDgEditor(title, 5, {
                readonly: true
            });
        } else if (roleType == 2) { //指定人员
            pp = $.yqDgEditor(title, 15, {
                readonly: false,
                "blank": "",
                "editType": 1,
                "editWidth": "450",
                "editHeight": "300",
                "param": {
                    "titles": [
                        {
                            "name": "sid",
                            "ui_title": "人员",
                            "ui_type": 7,
                            "ui_width": 140,
                            "ui_visible": true,
                            "ui_readonly": false,
                            "ui_mask": {
                                "dbName": "yqbase",
                                "tbName": "hr_user",
                                "tempNo": 100,
                                "displayType": 2,
                                "valueMember": "sid",
                                "displayMember": "name",
                                "isPage": true,
                                "pageSize": 10,
                                "order": "name",
                                "mapping": [
                                    {
                                        "from": "name",
                                        "to": "name"
                                    }
                                ],
                                "panelWidth": 600,
                                "panelHeight": 450,
                                "seekSimple": true,
                                "seekSimpleDDLW": 120,
                                "seekSimpleTxtW": 150,
                                "isSeek": true,
                                "seekNo": -1,
                                "seekModeW": 800,
                                "seekModeH": 600
                            }
                        }, {
                            "is_func": false,
                            "name": "name",
                            "ui_title": "name",
                            "ui_type": 2,
                            "ui_width": 150,
                            "ui_visible": true,
                            "ui_readonly": true,
                        }
                    ],
                    "model": []
                }
            });
        }
        else if (roleType == 3) { //指定岗位
            pp = $.yqDgEditor(title, 15, {
                readonly: false,
                "blank": "",
                "editType": 1,
                "editWidth": "450",
                "editHeight": "300",
                "param": {
                    "titles": [
                        {
                            "name": "sid",
                            "ui_title": "岗位",
                            "ui_type": 7,
                            "ui_width": 140,
                            "ui_visible": true,
                            "ui_readonly": false,
                            "ui_mask": {
                                "dbName": "yqbase",
                                "tbName": "hr_post",
                                "tempNo": 100,
                                "displayType": 2,
                                "valueMember": "sid",
                                "displayMember": "name",
                                "isPage": true,
                                "pageSize": 10,
                                "order": "name",
                                "mapping": [
                                    {
                                        "from": "name",
                                        "to": "name"
                                    }
                                ],
                                "panelWidth": 600,
                                "panelHeight": 450,
                                "seekSimple": true,
                                "seekSimpleDDLW": 120,
                                "seekSimpleTxtW": 150,
                                "isSeek": true,
                                "seekNo": -1,
                                "seekModeW": 800,
                                "seekModeH": 600
                            }
                        }, {
                            "is_func": false,
                            "name": "name",
                            "ui_title": "name",
                            "ui_type": 2,
                            "ui_width": 150,
                            "ui_visible": true,
                            "ui_readonly": true,
                        }
                    ],
                    "model": []
                }
            });
        }
        else if (roleType == 4) { //指定部门+职位
            pp = $.yqDgEditor(title, 15, {
                readonly: false,
                "blank": "",
                "editType": 1,
                "editWidth": "450",
                "editHeight": "300",
                "param": {
                    "titles": [
                        {
                            "name": "sid",
                            "ui_title": "部门",
                            "ui_type": 7,
                            "ui_width": 140,
                            "ui_visible": true,
                            "ui_readonly": false,
                            "ui_mask": {
                                "dbName": "yqbase",
                                "tbName": "hr_org",
                                "tempNo": 100,
                                "displayType": 2,
                                "valueMember": "sid",
                                "displayMember": "name",
                                "isPage": true,
                                "pageSize": 10,
                                "order": "name",
                                "mapping": [
                                    {
                                        "from": "name",
                                        "to": "name"
                                    }
                                ],
                                "panelWidth": 600,
                                "panelHeight": 450,
                                "seekSimple": true,
                                "seekSimpleDDLW": 120,
                                "seekSimpleTxtW": 150,
                                "isSeek": true,
                                "seekNo": -1,
                                "seekModeW": 800,
                                "seekModeH": 600
                            }
                        }, {
                            "is_func": false,
                            "name": "name",
                            "ui_title": "name",
                            "ui_type": 2,
                            "ui_width": 150,
                            "ui_visible": true,
                            "ui_readonly": true,
                        }, {
                            "is_func": false,
                            "name": "post_type",
                            "ui_title": "职位",
                            "ui_type": 6,
                            "ui_width": 80,
                            "ui_visible": true,
                            "ui_readonly": false,
                            "ui_mask": {
                                "lists": [
                                    {
                                        "no": "1",
                                        "name": "正职"
                                    }, {
                                        "no": "2",
                                        "name": "副职"
                                    }, {
                                        "no": "3",
                                        "name": "助理"
                                    }
                                ],
                                "default": -1
                            }
                        }
                    ],
                    "model": []
                }
            });
        }
        else if (roleType == 5) { //发起人部门+职位
            pp = $.yqDgEditor(title, 15, {
                readonly: false,
                "blank": "",
                "editType": 1,
                "editWidth": "450",
                "editHeight": "300",
                "param": {
                    "titles": [
                        {
                            "name": "level",
                            "ui_title": "层级",
                            "ui_type": 10,
                            "ui_width": 80,
                            "ui_visible": true,
                            "ui_readonly": false,
                            "ui_mask": {
                                "default": "1",
                                "blank": false,
                                "min": 1,
                                "max": 5
                            }
                        }, {
                            "is_func": false,
                            "name": "post_type",
                            "ui_title": "职位",
                            "ui_type": 6,
                            "ui_width": 80,
                            "ui_visible": true,
                            "ui_readonly": false,
                            "ui_mask": {
                                "lists": [
                                    {
                                        "no": "1",
                                        "name": "正职"
                                    }, {
                                        "no": "2",
                                        "name": "副职"
                                    }, {
                                        "no": "3",
                                        "name": "助理"
                                    }
                                ],
                                "default": -1
                            }
                        }
                    ],
                    "model": []
                }
            });
        }
        else if (roleType == 99) { //按代码
            pp = $.yqDgEditor(title, 5, {
                "ui_visible": true,
                "ui_readonly": false,
                "ui_mask": {
                    "default": "base",
                    "types": [
                        "base"
                    ],
                    "blank": false,
                    "editModeW": 400,
                    "editModeH": 300
                }
            });
        } else {
            pp = $.yqDgEditor(title, 1, {
                readonly: true,
            });
        }

        return pp;
    }

    function init_jsonview($object) {
        var opt = options($object);
        var $uniqueID = $object.attr("ID");

        info_edit($object);
        form_load($object);
    }

    function load($object, value) {
        var opt = options($object);
        if (value === undefined) {
            value = opt.value;
        } else {
            if (value === null) {
                value = {};
            }
            opt.value = value;
        }

        var json_ = typeof value == "string" ? JSON.parse(value) : value;
        if (json_.node === undefined) {
            json_.node = [];
        }
        if (json_.link === undefined) {
            json_.link = [];
        }
        if (json_.info === undefined) {
            json_.info = {};
        }
        opt.value = json_;

        if (!(opt.$jsonview === undefined)) {
            opt.$jsonview.val($.jsonFormat(opt.value));
        }
        var j_ = {
            "class": "GraphLinksModel",
            "linkFromPortIdProperty": "fromPort",
            "linkToPortIdProperty": "toPort",
        };

        for (var i = 0; i < json_.link.length; i++) {
            if (typeof json_.link[i].points === "string") {
                json_.link[i].points = JSON.parse("[" + json_.link[i].points + "]");
            }
        }

        j_.nodeDataArray = json_.node;
        j_.linkDataArray = json_.link;

        opt.diagram.model = go.Model.fromJson(j_);
        info_edit($object);
    }

    function getModel($object) {
        var opt = options($object);
        var json_ = model_to_json(opt, opt.diagram.model.toJson());
        json_ = $.extend({ info: opt.value.info }, json_);
        json_ = $.jsonRemoveEmpty(json_);
        opt.value = json_;

        return json_;
    }

    function model_to_json(opt, json_) {
        var j_ = {};
        json_ = typeof json_ == "string" ? JSON.parse(json_) : json_;
        j_.node = json_.nodeDataArray;
        j_.link = json_.linkDataArray;

        var node = [];
        for (var i = 0; i < j_.node.length; i++) {
            if (j_.node[i].category == "Start") {
                j_.node[i].class = 1;
                node.push(j_.node[i]);
                break;
            }
        }
        for (var i = 0; i < j_.node.length; i++) {
            if (j_.node[i].category == "Return") {
                j_.node[i].class = 2;
                node.push(j_.node[i]);
                break;
            }
        }
        for (var i = 0; i < j_.node.length; i++) {
            //console.log(j_.node[i].loc);
            var locs = j_.node[i].loc.split(" ");
            j_.node[i].loc = (locs[0].indexOf(".") > 0 ? parseFloat(locs[0]).toFixed(2) : locs[0])
                + " "
                + (locs[1].indexOf(".") > 0 ? parseFloat(locs[1]).toFixed(2) : locs[1]);

            if (!(j_.size === undefined)) {
                var sizes = j_.node[i].size.split(" ");
                j_.node[i].size = (sizes[0].indexOf(".") > 0 ? parseFloat(sizes[0]).toFixed(0) : sizes[0])
                    + " "
                    + (sizes[1].indexOf(".") > 0 ? parseFloat(sizes[1]).toFixed(0) : sizes[1]);
            }

            if (j_.node[i].desc === undefined ||
                j_.node[i].desc === null ||
                j_.node[i].desc == "") {
                j_.node[i].desc = j_.node[i].text;
            }

            if (j_.node[i].category == "Exec") {
                j_.node[i].class = 5;

                if (j_.node[i].roleIsEdit === undefined) {
                    j_.node[i].roleIsEdit = false;
                }
                if (j_.node[i].rolePass === undefined) {
                    j_.node[i].rolePass = false;
                }

                //
                if (j_.node[i].roleType === undefined ||
                    j_.node[i].roleType === null) {
                    delete j_.node[i].roleType;
                    delete j_.node[i].roleMark;
                } else if (j_.node[i].roleType == 1) {
                    delete j_.node[i].roleMark;
                }

                //通过方式
                if (j_.node[i].duplicateType === undefined ||
                    j_.node[i].duplicateType === null ||
                    j_.node[i].duplicateType < 1 ||
                    j_.node[i].duplicateType > 4) {
                    j_.node[i].duplicateType = 1;
                }

                if (j_.node[i].duplicateType == 1 ||   //单人审批
                    j_.node[i].duplicateType == 4) {   //全部通过
                    delete j_.node[i].duplicateNum;
                } else if (j_.node[i].duplicateType == 2) { //最小通过人数
                    if (j_.node[i].duplicateNum === undefined || j_.node[i].duplicateNum === null) {
                        j_.node[i].duplicateNum = 1;
                    }

                    if (j_.node[i].duplicateNum < 1) {
                        j_.node[i].duplicateNum = 1;
                    }
                } else if (j_.node[i].duplicateType == 3) { //最小通过百分比
                    if (j_.node[i].duplicateNum === undefined || j_.node[i].duplicateNum === null) {
                        j_.node[i].duplicateNum = 100;
                    }

                    if (j_.node[i].duplicateNum < 0 || j_.node[i].duplicateNum > 100) {
                        j_.node[i].duplicateNum = 100;
                    }
                }

            } else if (j_.node[i].category == "Proc") {
                j_.node[i].class = 7;
            } else if (j_.node[i].category == "Judge") {
                j_.node[i].class = 6;
            }

            if (j_.node[i].category == "Exec" ||
                j_.node[i].category == "Proc" ||
                j_.node[i].category == "Judge") {

                //程序节点
                if (j_.node[i].category == "Proc") {
                    var s_node = opt.diagram.findNodeForKey(j_.node[i].key);
                    var lines = s_node.findLinksOutOf();
                    console.log("lines", lines.count);
                    if (lines.count == 0) {
                        opt.diagram.model.setDataProperty(s_node.data, "type", 1);
                        j_.node[i].type = 1;
                    } else {
                        opt.diagram.model.setDataProperty(s_node.data, "type", 2);
                        j_.node[i].type = 2;
                    }
                }

                node.push(j_.node[i]);
            }
        }
        for (var i = 0; i < j_.node.length; i++) {
            if (j_.node[i].category == "Cancle") {
                j_.node[i].class = 8;
                node.push(j_.node[i]);
                break;
            }
        }
        for (var i = 0; i < j_.node.length; i++) {
            if (j_.node[i].category == "End") {
                j_.node[i].class = 9;
                node.push(j_.node[i]);
                break;
            }
        }
        for (var i = 0; i < j_.node.length; i++) {
            if (j_.node[i].category == "Comment") {
                j_.node[i].class = 10;
                node.push(j_.node[i]);
                break;
            }
        }
        j_.node = node;

        for (var i = 0; i < j_.link.length; i++) {
            var points = [];
            for (var j = 0; j < j_.link[i].points.length; j++) {
                var point = j_.link[i].points[j].toString();
                if (point.indexOf(".") > 0) {
                    point = parseFloat(j_.link[i].points[j].toFixed(2));
                } else {
                    point = j_.link[i].points[j];
                }
                points.push(point);
            }
            var tmp = JSON.stringify(points);
            j_.link[i].points = tmp.substring(1, tmp.length - 1);

            if (j_.link[i].desc === undefined ||
                j_.link[i].desc === null ||
                j_.link[i].desc == "") {
                j_.link[i].desc = j_.link[i].text;
            }

            if (!(j_.link[i].fromPort === undefined)) {
                delete j_.link[i].fromPort;
            }
            if (!(j_.link[i].toPort === undefined)) {
                delete j_.link[i].toPort;
            }
        }

        return j_;
    }

    //流程打印
    function printDiagram($object) {
        var opt = options($object);
        var svgWindow = window.open();
        if (!svgWindow) return;  // failure to open a new Window
        var printSize = new go.Size(700, 960);
        var bnds = opt.diagram.documentBounds;
        var x = bnds.x;
        var y = bnds.y;
        while (y < bnds.bottom) {
            while (x < bnds.right) {
                var svg = opt.diagram.makeSvg({ scale: 1.0, position: new go.Point(x, y), size: printSize });
                svgWindow.document.body.appendChild(svg);
                x += printSize.width;
            }
            x = bnds.x;
            y += printSize.height;
        }

        setTimeout(function () {
            svgWindow.print()
            svgWindow.close();
        }, 1);
    }

    //排序
    function orderDiagram($object, $btn) {
        var opt = options($object);

        var titles = [
            {
                "name": "key",
                "ui_title": "key",
                "ui_type": 10,
                "ui_width": 40,
                "ui_visible": true,
                "ui_readnnly": false,
                "ui_mask": {}
            }, {
                "name": "category",
                "ui_title": "category",
                "ui_type": 2,
                "ui_width": 80,
                "ui_visible": true,
                "ui_readnnly": false,
                "ui_mask": {}
            }, {
                "name": "text",
                "ui_title": "text",
                "ui_type": 2,
                "ui_width": 390,
                "ui_visible": true,
                "ui_readnnly": false,
                "ui_mask": {}
            }
        ];

        var val = getModel($object);

        var rows = JSON.parse(JSON.stringify(val.node));

        var prevent_e = $.getPreventDefault($btn[0]);
        prevent_e.id = $btn.attr("id");
        prevent_e.options = {};

        var mdiinfo = $.yqGetWindParams();

        var move_pops = {
            ajaxUrl: "/_db.html",
            prevent_e: prevent_e,
            mdiinfo: mdiinfo,
            title: "move",
            width: 570,
            height: 400,
            titles: titles,
            rows: rows,
            callback: function (rows) {
                var node = [];
                for (var i = 0; i < rows.length; i++) {
                    for (var j = 0; j < val.node.length; j++) {
                        if (rows[i]["key"] == val.node[j]["key"]) {
                            val.node[j]["_key"] = i + 1;
                            node.push(val.node[j]);
                        }
                    }

                    for (var j = 0; j < val.link.length; j++) {
                        if (rows[i]["key"] == val.link[j]["from"]) {
                            val.link[j]["_from"] = i + 1;
                        }
                        if (rows[i]["key"] == val.link[j]["to"]) {
                            val.link[j]["_to"] = i + 1;
                        }
                    }
                }
                val.node = node;
                for (var j = 0; j < val.node.length; j++) {
                    val.node[j]["key"] = val.node[j]["_key"];
                    delete val.node[j]["_key"];
                }
                for (var j = 0; j < val.link.length; j++) {
                    val.link[j]["from"] = val.link[j]["_from"];
                    val.link[j]["to"] = val.link[j]["_to"];
                    delete val.link[j]["_from"];
                    delete val.link[j]["_to"];
                }

                load($object, val);
            }
        };

        if (window.top == window.self) {
            $.yqRowsPopMove(move_pops);
        }
        else {
            window.top.$.yqRowsPopMove(move_pops);
        }
    }

    //保存json
    function saveDiagram($object, filename) {
        var text = $.jsonFormat(getModel($object));

        var blob = new Blob([text], { type: "text/plain;charset=utf-8" });
        var url = URL.createObjectURL(blob);
        var link = document.createElement('a');
        link.href = url;
        link.download = (filename === undefined ? "flow.json" : filename);
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
    }

    function loadFile($object) {
        var opt = options($object);
        if (opt.fileselect === undefined) {
            var input = document.createElement('input');
            input.type = "file";
            input.accept = ".json,.txt";
            input.style = "display: none";
            document.body.appendChild(input);
            input.addEventListener('change', function (e) {
                var file = e.target.files[0]; // 获取选中的文件  
                if (file) {
                    var fileType = file.type; // 获取文件类型  
                    var allowedTypes = ['text/plain', 'application/json']; // 允许的文件类型  
                    if (allowedTypes.includes(fileType)) {
                        var reader = new FileReader();
                        reader.onload = function (e) {
                            try {
                                var _j = JSON.parse(e.target.result);
                                load($object, _j);
                            }
                            catch (err) {
                                console.error("filejson", err);
                                $.yqMessager("error", "内容格式错误。");
                            }
                        };
                        reader.readAsText(file);  // 读取文件内容为文本 
                    }
                }
            });

            opt.fileselect = input;
        }
        opt.fileselect.click();
    }
})(jQuery);
